package com.baijiayun.live.ui.chat

import android.animation.Animator
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.ImageSpan
import android.text.util.Linkify
import android.view.*
import android.widget.*
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.GestureDetectorCompat
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
import com.baijiayun.glide.Glide
import com.baijiayun.glide.request.RequestOptions
import com.baijiayun.glide.request.target.SimpleTarget
import com.baijiayun.glide.request.transition.Transition
import com.baijiayun.live.ui.R
import com.baijiayun.live.ui.activity.LiveRoomBaseActivity
import com.baijiayun.live.ui.atMostViewSize
import com.baijiayun.live.ui.base.BasePadFragment
import com.baijiayun.live.ui.base.getViewModel
import com.baijiayun.live.ui.chat.preview.ChatPictureViewFragment
import com.baijiayun.live.ui.chat.preview.ChatPictureViewPresenter
import com.baijiayun.live.ui.chat.preview.ChatSavePicDialogFragment
import com.baijiayun.live.ui.chat.preview.ChatSavePicDialogPresenter
import com.baijiayun.live.ui.chat.utils.CenterImageSpan
import com.baijiayun.live.ui.chat.utils.URLImageParser
import com.baijiayun.live.ui.chat.widget.ChatMessageView
import com.baijiayun.live.ui.databinding.ItemPadChatBinding
import com.baijiayun.live.ui.isAdmin
import com.baijiayun.live.ui.utils.ChatImageUtil
import com.baijiayun.livecore.context.LPConstants
import com.baijiayun.livecore.models.LPMessageModel
import com.baijiayun.livecore.models.LPUserModel
import com.baijiayun.livecore.models.imodels.IMessageModel
import com.baijiayun.livecore.models.imodels.IUserModel
import com.baijiayun.livecore.ppt.util.AliCloudImageUtil
import com.baijiayun.livecore.utils.CommonUtils
import com.baijiayun.livecore.utils.LPChatMessageParser
import com.baijiayun.livecore.utils.LPRxUtils
import com.baijiayun.liveuibase.utils.DisplayUtils
import com.baijiayun.liveuibase.utils.DisplayUtils.isPad
import com.baijiayun.liveuibase.utils.LinearLayoutWrapManager
import com.baijiayun.liveuibase.utils.ThemeDataUtil
import com.baijiayun.liveuibase.utils.drawable.DrawableBuilder
import com.baijiayun.liveuibase.utils.isOnlyEmojis
import com.baijiayun.liveuibase.widgets.dialog.ReportDialog
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.fragment_pad_chat_list.*
import kotlinx.android.synthetic.main.item_pad_chat.view.*
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.lang.ref.WeakReference
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern

/**
 * Created by yongjiaming on 2019-10-23
 * Describe:
 */
class ChatPadFragment : BasePadFragment(), ChatMessageView.IChatMessageListener {

    private val stickyMessages: MutableList<LPMessageModel> = ArrayList()

    private lateinit var recyclerView: RecyclerView
    private lateinit var stickyContainer: ConstraintLayout
    private lateinit var messageReminderContainer: LinearLayout
    private var currentPosition = 0
    private val MESSAGE_TYPE_TEXT = 0
    private val MESSAGE_TYPE_IMAGE = 1
    private lateinit var languageTranslateTo: String

    private val messageAdapter by lazy {
        MessageAdapter()
    }

    private val navigateToMainObserver by lazy {
        Observer<Boolean> {
            if (it == true) {
                initSuccess()
            }
        }
    }

    private lateinit var chatViewModel: ChatViewModel

    private val simpleDataFormat by lazy {
        SimpleDateFormat("HH:mm", Locale.getDefault())
    }

    private val pattern: Pattern = Pattern.compile("\\[[a-zA-Z0-9\u4e00-\u9fa5]+]")


    private lateinit var failedColorDrawable: ColorDrawable
    private lateinit var sendMessageBtn: TextView
    private lateinit var noMessageTv: TextView

    private lateinit var stickyPackUp: ImageView
    private lateinit var stickyItemContainerScroller: ScrollView
    private lateinit var stickyItemContainer: LinearLayout
    private lateinit var stickyOutOfThree: TextView
    private var isInit = false

    private var savePictureDisposable: Disposable? = null
    private var lotteryTimerDispose: Disposable? = null

    override fun init(view: View) {
        activity?.run {
            chatViewModel = getViewModel {
                ChatViewModel(routerViewModel)
            }
        }
        languageTranslateTo = Locale.getDefault().language
        recyclerView = view.findViewById(R.id.chat_recycler_view)
        stickyContainer = view.findViewById(R.id.fragment_chat_sticky_container)
        stickyPackUp = stickyContainer.findViewById(R.id.fragment_chat_sticky_pack_up)
        stickyItemContainerScroller =
            stickyContainer.findViewById(R.id.fragment_chat_sticky_scroll_container)
        stickyItemContainer = stickyContainer.findViewById(R.id.fragment_chat_sticky_item_container)
        stickyOutOfThree = view.findViewById(R.id.fragment_chat_sticky_out_of_3)
        stickyContainer.visibility = View.GONE

        messageReminderContainer =
            view.findViewById(R.id.activity_live_room_new_message_reminder_container)
        messageReminderContainer.background = DrawableBuilder()
            .solidColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_live_product_color))
            .cornerRadius(context!!.resources!!.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius))
            .build()
        context?.let {
            failedColorDrawable =
                ColorDrawable(ContextCompat.getColor(it, R.color.live_half_transparent))
        }
        sendMessageBtn = view.findViewById(R.id.send_message_btn)
        sendMessageBtn.background = getInputBG()
        sendMessageBtn.setOnClickListener {
            routerViewModel.actionShowSendMessageFragment.value = ""
        }
        send_message_btn_back.setOnClickListener {
            routerViewModel.action2Chat.value = false
        }
        fragment_chat_private_end_btn.setOnClickListener {
            context?.let {
                routerViewModel.privateChatUser.value = null
                showToastMessage(it.getString(R.string.live_room_private_chat_cancel))
                messageAdapter.notifyDataSetChanged()
            }
        }
        fragment_chat_filter_close.setOnClickListener {
            filterMessage(false)
        }
        //私聊打开消息发送界面同时打开用户列表
        chat_private_start.setOnClickListener {
            routerViewModel.choosePrivateChatUser = true
            routerViewModel.actionShowSendMessageFragment.value = ""
        }
        chat_private_start.background = getInputBG()
        noMessageTv = view.findViewById(R.id.chat_no_message_tv)
        tvCommand.setOnClickListener {
            routerViewModel.actionShowSendMessageFragment.value = tvCommand.text.toString()
        }
        fragment_chat_command_bubble_container.background = DrawableBuilder()
            .solidColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_brand_container_color))
            .cornerRadius(context!!.resources.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius))
            .strokeWidth(1)
            .strokeColor(ContextCompat.getColor(context!!, R.color.base_bg_stroke))
            .build()
        language_select_btn.visibility = if (routerViewModel.liveRoom.partnerConfig.isEnableChatTranslation) View.VISIBLE else View.GONE
        language_select_btn.setOnClickListener {
            language_select_btn.isSelected = true
            val popupWindow = PopupWindow(context)
            popupWindow.isFocusable = true
            popupWindow.width = DisplayUtils.dip2px(context!!, 100f)
            popupWindow.setBackgroundDrawable(ColorDrawable(0))
            popupWindow.height = ViewGroup.LayoutParams.WRAP_CONTENT
            popupWindow.setOnDismissListener {
                language_select_btn.isSelected = false
            }
            val items = mutableListOf<String>()
            items.add(context!!.getString(R.string.bjy_live_translate_language_english))
            items.add(context!!.getString(R.string.bjy_live_translate_language_japanese))
            items.add(context!!.getString(R.string.bjy_live_translate_language_vietnamese))
            items.add(context!!.getString(R.string.bjy_live_translate_language_indonesian))
            items.add(context!!.getString(R.string.bjy_live_translate_language_simplified_chinese))
            items.add(context!!.getString(R.string.bjy_live_translate_language_traditional_chinese))
            val listView = ListView(context)
            val adapter = LanguageSelectMenuAdapter(
                items, context!!, when (languageTranslateTo) {
                    "en" -> 0
                    "jp" -> 1
                    "vie" -> 2
                    "id" -> 3
                    "cht" -> 5
                    else -> 4
                }
            )
            val bgDrawable = GradientDrawable()
            bgDrawable.setColor(
                ThemeDataUtil.getColorFromThemeConfigByAttrId(
                    context,
                    R.attr.base_theme_window_bg_color
                )
            )
            bgDrawable.cornerRadius = 3f
            bgDrawable.setStroke(1, ContextCompat.getColor(context!!, R.color.base_bg_stroke_10))
            listView.background = bgDrawable
            listView.adapter = adapter
            listView.dividerHeight = 0
            listView.setOnItemClickListener { parent, view, position, id ->
                setLanguageSelect(listView, position, items.size)
                popupWindow.dismiss()
            }
            popupWindow.contentView = listView
            val location = intArrayOf(0, 0)
            language_select_btn.getLocationOnScreen(location)
            val measuredHeight = atMostViewSize(listView)[1]
            popupWindow.showAtLocation(
                language_select_btn,
                Gravity.NO_GRAVITY,
                location[0] - DisplayUtils.dip2px(context!!, 100.toFloat()),
                location[1] - measuredHeight - 5
            )
        }
        refresh_layout.setOnRefreshListener {
            chatViewModel.loadMoreWhisperList()
        }
        refresh_layout.isEnabled = false
    }

    private fun setLanguageSelect(listView: ListView, position: Int, size: Int) {
        for (i in 0 until size) {
            if (i == position) {
                listView.getChildAt(i).findViewById<ImageView>(R.id.ic_language_is_selected).visibility = View.VISIBLE
                listView.getChildAt(i).findViewById<TextView>(R.id.tv_language).setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_live_product_color))
                when (i) {
                    0 -> languageTranslateTo = "en"
                    1 -> languageTranslateTo = "jp"
                    2 -> languageTranslateTo = "vie"
                    3 -> languageTranslateTo = "id"
                    4 -> languageTranslateTo = "zh"
                    5 -> languageTranslateTo = "cht"
                }
            } else {
                listView.getChildAt(i)
                    .findViewById<ImageView>(R.id.ic_language_is_selected).visibility =
                    View.INVISIBLE
                listView.getChildAt(i).findViewById<TextView>(R.id.tv_language).setTextColor(
                    ThemeDataUtil.getColorFromThemeConfigByAttrId(
                        context,
                        R.attr.base_theme_window_main_text_color
                    )
                )
            }
        }
    }

    private fun getInputBG(): Drawable {
        val rstDrawable = StateListDrawable()
        rstDrawable.addState(
            IntArray(1, init = { android.R.attr.state_enabled }), DrawableBuilder()
                .solidColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_window_bg_color))
                .cornerRadius(context!!.resources!!.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius))
                .strokeColor(ContextCompat.getColor(context!!, R.color.base_bg_stroke))
                .strokeWidth(1)
                .build()
        )
        rstDrawable.addState(
            IntArray(1, init = { -android.R.attr.state_enabled }), DrawableBuilder()
                .solidColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_window_bg_color))
                .cornerRadius(context!!.resources!!.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius))
                .strokeColor(ContextCompat.getColor(context!!, R.color.base_bg_stroke))
                .strokeWidth(1)
                .build()
        )
        return rstDrawable
    }

    override fun observeActions() {
        routerViewModel.actionNavigateToMain.observeForever(navigateToMainObserver)
    }

    private fun initSuccess() {
        chat_private_start.visibility =
            if (routerViewModel.liveRoom.chatVM.isLiveCanWhisper) View.VISIBLE else View.GONE
        recyclerView.layoutManager = LinearLayoutWrapManager(context)
        recyclerView.adapter = messageAdapter

        chatViewModel.notifyDataSetChange.observe(this, Observer {
            refresh_layout.isRefreshing = false
            val msgCount = chatViewModel.receivedNewMsgNum
            var needScroll = false
            //滑动规则：在当前页面，接收到自己消息滑动
            //接收别人的消息在消息底部或者底部-1的位置滑动
            if (routerViewModel.action2Chat.value == true) {
                if (chatViewModel.receiveMsgType == ChatViewModel.MsgType.Me) {
                    needScroll = true
                } else {
                    if (currentPosition >= chatViewModel.getCount() - 2 && msgCount > 0) {
                        needScroll = true
                    }
                }
                chatViewModel.receiveMsgType = ChatViewModel.MsgType.None
            }
            if (!needScroll) {
                showMessageReminder(true)
            }
            messageAdapter.notifyDataSetChanged()
            if ((!isInit || needScroll) && ::recyclerView.isInitialized && messageAdapter.itemCount > 0) {
                val linearLayoutWrapManager = recyclerView.layoutManager
                if (linearLayoutWrapManager is LinearLayoutWrapManager && !isInit) {
                    linearLayoutWrapManager.scrollToPositionWithOffset(
                        messageAdapter.itemCount - 1,
                        0
                    )
                } else {
                    recyclerView.smoothScrollToPosition(messageAdapter.itemCount - 1)
                }
                isInit = true
            }
            noMessageTv.visibility = if (chatViewModel.getCount() > 0) View.GONE else View.VISIBLE
        })

        chatViewModel.notifyLoadDataComplete.observe(this, Observer {
            it?.let {
                refresh_layout.isRefreshing = false
            }
        })

        chatViewModel.notifyItemChange.observe(this, Observer {
            it?.run {
                messageAdapter.notifyItemChanged(it)
            }
        })

        chatViewModel.notifyItemInsert.observe(this, Observer {
            it?.run {
                messageAdapter.notifyItemInserted(it)
                noMessageTv.visibility =
                    if (chatViewModel.getCount() > 0) View.GONE else View.VISIBLE
            }
        })

        chatViewModel.notifyStickyMessage.observe(this, Observer {
            it?.run {
                stickyMessages.clear()
                if (it.isNotEmpty()) {
                    forEach { messageModel: IMessageModel -> stickyMessages.add(messageModel as LPMessageModel) }
                }
                setChatSticky()
            }
        })

        chatViewModel.notifyLotteryEnd.observe(this, Observer {
            it?.let {
                fragment_chat_command_bubble_container.visibility = View.GONE
                showToastMessage(getString(R.string.live_lottery_command_participated))
            }
        })

        routerViewModel.privateChatUser.observe(this, Observer {
            if (chatViewModel.isPrivateChatMode()) {
                // 拉取私聊消息
                chatViewModel.loadFirstWhisperList()
                showHavingPrivateChat(routerViewModel.privateChatUser.value!!)
                // 进入私聊取消只看老师
                filterMessage(false)
            } else {
                showNoPrivateChat()
            }
            refresh_layout.isEnabled = chatViewModel.isPrivateChatMode()
            messageAdapter.notifyDataSetChanged()
            noMessageTv.visibility = if (chatViewModel.getCount() > 0) View.GONE else View.VISIBLE
        })
        chatViewModel.subscribe()
        if (routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.Single || routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.OneOnOne) {
            if (!isPad(context!!)) {
                send_message_btn_back.visibility = View.VISIBLE
            }
            chat_private_start.visibility = View.GONE
        }
        routerViewModel.sendPictureMessage.observe(this, Observer {
            it?.run {
                chatViewModel.sendImageMessage(this)
            }
        })

        routerViewModel.showSavePicDialog.observe(this, Observer {
            it?.run {
                showSavePicDialog(this)
            }
        })

        routerViewModel.action2ChatBottom.observe(this, Observer {
            it?.run {
                if (::recyclerView.isInitialized && messageAdapter.itemCount > 0) {
                    recyclerView.smoothScrollToPosition(messageAdapter.itemCount - 1)
                }
            }
        })

        routerViewModel.saveChatPictureToGallery.observe(this, Observer {
            it?.run {
                saveImageToGallery(this)
            }
        })

        routerViewModel.actionCommandLotteryStart.observe(this, Observer {
            it?.let {
                //口令抽奖开始
                val time = it.beginTime + it.duration - System.currentTimeMillis() / 1000
                if (time > 0) {
                    chatViewModel.isLotterying = true
                    showToastMessage(getString(R.string.live_lottery_command_start))
                    fragment_chat_command_bubble_container.visibility = View.VISIBLE
                    fragment_chat_command_countdown_container.visibility = View.VISIBLE
                    tvCommand.text = it.command
                    fragment_chat_command_countdown_tv.text = time.toString()
                    startLotteryTimer(time)
                }
            }
        })

        routerViewModel.action2Lottery.observe(this, Observer {
            it?.let {
                //口令抽奖结束
                if (it.lotteryType == 1) {
                    chatViewModel.isLotterying = false
                    fragment_chat_command_bubble_container.visibility = View.GONE
                    fragment_chat_command_countdown_container.visibility = View.GONE
                    LPRxUtils.dispose(lotteryTimerDispose)
                }
            }
        })

        chatViewModel.notifyForbidChat.observe(this, Observer {
            it?.let {
                showForbidChatState(it)
            }
        })

        chatViewModel.onlineUserGroup.observe(this, Observer{
            it.let {
                messageAdapter.notifyDataSetChanged()
            }
        })

        showForbidChatState(routerViewModel.liveRoom.forbidAllChatStatus)
    }

    private fun showForbidChatState(forbidChat: Boolean) {
        if (isAdmin(routerViewModel.liveRoom)) {
            return
        }
        send_message_btn.isEnabled = !forbidChat
        send_message_btn.text =
            getString(if (forbidChat) R.string.live_chat_enter_forbid_tip else R.string.live_chat_enter_tip)
        //禁言且不能私聊
        chat_private_start.isEnabled =
            !chatViewModel.isSelfForbidden && (!forbidChat || chatViewModel.canWhisperTeacherInForbidAllMode())
    }

    private fun startLotteryTimer(time: Long) {
        LPRxUtils.dispose(lotteryTimerDispose)
        lotteryTimerDispose = Observable.interval(1, 1, TimeUnit.SECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                fragment_chat_command_countdown_tv.text = (time - it).toString()
                if (it == time) {
                    chatViewModel.isLotterying = false
                    fragment_chat_command_bubble_container.visibility = View.GONE
                    fragment_chat_command_countdown_container.visibility = View.GONE
                    LPRxUtils.dispose(lotteryTimerDispose)
                }
            }
    }

    private fun cancelSticky(message: IMessageModel) {
        for (stickyMessage in stickyMessages) {
            if (stickyMessage.id == message.id) {
                stickyMessages.remove(stickyMessage)
                chatViewModel.stickyMessage(stickyMessages)
                return
            }
        }
    }

    private fun addSticky(message: IMessageModel) {
        if (containsMessageInSticky(message)) {
            return
        }
        if (stickyMessages.size < 3) {
            stickyMessages.add(0, message as LPMessageModel)
            chatViewModel.stickyMessage(stickyMessages)
        } else {
            startStickyWarningAnim()
        }
    }

    private fun containsMessageInSticky(message: IMessageModel): Boolean = let {
        for (stickyMessage in stickyMessages) {
            if (stickyMessage.id == message.id) {
                return@let true
            }
        }
        false
    }

    private fun startStickyWarningAnim() {
        stickyOutOfThree.visibility = View.VISIBLE
        stickyOutOfThree.alpha = 1f
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            val anim = ObjectAnimator.ofFloat(stickyOutOfThree, "alpha", 1f, 0f)
            anim.duration = 500
            anim.startDelay = 2000
            anim.addListener(object : Animator.AnimatorListener {
                override fun onAnimationRepeat(animation: Animator?) {}

                override fun onAnimationEnd(animation: Animator?) {
                    stickyOutOfThree.visibility = View.GONE
                }

                override fun onAnimationCancel(animation: Animator?) {}

                override fun onAnimationStart(animation: Animator?) {}
            })
            anim.start()
        } else {
            stickyOutOfThree.postDelayed({
                stickyOutOfThree.visibility = View.GONE
            }, 2000)
        }
    }

    private val stickyItems = ArrayList<StickyItemLinearLayout>()

    private fun updateAllStickyItemDetail(isDetail: Boolean) {
        for (stickyItem in stickyItems) {
            stickyItem.updateLayoutForDetail(isDetail)
        }
    }

    @SuppressLint("SetTextI18n", "ClickableViewAccessibility")
    private fun setChatSticky() {
        stickyItemContainer.removeAllViews()
        stickyItems.clear()
        if (stickyMessages.isEmpty()) {
            val params = (refresh_layout.layoutParams as RelativeLayout.LayoutParams)
            params.addRule(RelativeLayout.BELOW, R.id.fragment_chat_private_status_container)
            params.topMargin = 0
            refresh_layout.layoutParams = params
            stickyContainer.visibility = View.GONE
            setChatStickyState(false)
            return
        }

        for ((index, messageModel) in stickyMessages.withIndex()) {
            messageModel.parse(LPChatMessageParser(chatViewModel.getExpressions()))

            val userName = getNameFromMessage(messageModel) + getRoleFromMessage(messageModel)
            val content = if (messageModel.type != LPConstants.MessageType.Image) {
                messageModel.content
            } else {
                messageModel.getUrl()
            }

            val stickyItem = StickyItemLinearLayout(context!!, index)
                .initListener(object : StickyItemLinearLayout.StickyItemListener {
                    override fun onContentClick() {
                        if (isDetail && messageModel.type == LPConstants.MessageType.Image) {
                            showBigChatPic(messageModel.url,ChatPictureViewFragment.IOnBigPicCancel {
                                cancelSticky(messageModel)
                            })
                        }
                        if (index == 0 && !isDetail) {
                            setChatStickyState(true)
                        }
                    }

                    override fun onCancelSticky() {
                        cancelSticky(messageModel)
                    }


                    override fun onGetMixText(src: CharSequence, textView: TextView): SpannableStringBuilder {
                        ChatPadFragment.apply {
                            return getMixText(src.toString(), textView)
                        }
                    }
                })
                .initValue(userName, content, messageModel.type == LPConstants.MessageType.Image)
                .setCancelStickyVisibility(
                    routerViewModel.liveRoom.isTeacherOrAssistant
                            || routerViewModel.liveRoom.isGroupTeacherOrAssistant
                )
            if (index == 0) {
                stickyItem.setStickyCount(stickyMessages.size)
            }

            stickyItemContainer.addView(stickyItem.contentView)
            stickyItems.add(stickyItem)
        }

        setChatStickyState(isDetail)
        stickyContainer.visibility = View.VISIBLE

        stickyPackUp.setOnClickListener {
            setChatStickyState(false)
        }
    }

    private var isDetail: Boolean = false

    //置顶按键显示状态
    @SuppressLint("SetTextI18n")
    private fun setChatStickyState(isDetail: Boolean) {
        this.isDetail = isDetail
        // 更新所有子 stickyItem
        updateAllStickyItemDetail(isDetail)
        stickyPackUp.visibility = if (isDetail) View.VISIBLE else View.GONE
        // region 更新 聊天区域容器属性、
        val layoutParams = refresh_layout.layoutParams as RelativeLayout.LayoutParams
        if (isDetail) {
            layoutParams.removeRule(RelativeLayout.BELOW)
        } else {
            layoutParams.addRule(RelativeLayout.BELOW, stickyContainer.id)
        }
        refresh_layout.layoutParams = layoutParams
        // endregion
    }

    override fun getLayoutId() = R.layout.fragment_pad_chat_list

    private fun showMessageReminder(needShow: Boolean) {
        if (!needShow || chatViewModel.receivedNewMsgNum <= 0) {
            messageReminderContainer.visibility = View.GONE
            chatViewModel.receivedNewMsgNum = 0
            if (routerViewModel.action2Chat.value == true) {
                chatViewModel.redPointNumber.value = 0
            }
            return
        }
        messageReminderContainer.visibility = View.VISIBLE
        messageReminderContainer.setOnClickListener {
            if (chatViewModel.getCount() > 0) {
                recyclerView.smoothScrollToPosition(chatViewModel.getCount() - 1)
            }
            chatViewModel.receivedNewMsgNum = 0
            chatViewModel.redPointNumber.value = 0
        }
    }

    inner class MessageAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val dataBinding: ItemPadChatBinding = DataBindingUtil.inflate(
                LayoutInflater.from(parent.context),
                R.layout.item_pad_chat,
                parent,
                false
            )
            val messageContainer = dataBinding.root.findViewById<FrameLayout>(R.id.chat_container)
            return when (viewType) {
                MESSAGE_TYPE_TEXT -> {
                    LayoutInflater.from(context)
                        .inflate(R.layout.item_pad_chat_text, messageContainer)
                    TextViewHolder(dataBinding, dataBinding.root)
                }
                MESSAGE_TYPE_IMAGE -> {
                    LayoutInflater.from(context)
                        .inflate(R.layout.bjy_item_chat_image, messageContainer)
                    ImageViewHolder(dataBinding, dataBinding.root)
                }
                else -> {
                    TextViewHolder(dataBinding, dataBinding.root)
                }
            }
        }

        override fun getItemCount() = chatViewModel.getCount()

        @SuppressLint("ClickableViewAccessibility", "RecyclerView")
        override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
            if (position < 0 || position >= itemCount) {
                return
            }
            currentPosition = position
            if (position == chatViewModel.getCount() - 1) {
                showMessageReminder(false)
            }
            val message: IMessageModel = chatViewModel.getMessage(position)
            showOptMenu(viewHolder, message.from)
            val ssb = SpannableStringBuilder()
            if (!chatViewModel.isPrivateChatMode() && message.isPrivateChat) {
                // 私聊item  首行显示私聊老师/助教
                if (!routerViewModel.liveRoom.chatVM.isLiveCanWhisper) return
                var spanText: SpannableString
                val isFromMe = message.from.userId == currentUserId()
                val isToMe = message.to == currentUserId()
                val toName =
                    if (message.toUser == null) message.to else getEncodedName(message.toUser)
                if (isFromMe) {
                    val source = "私聊  "
                    spanText = SpannableString(source + toName)
                    spanText.setSpan(
                        ForegroundColorSpan(
                            ContextCompat.getColor(
                                context!!,
                                R.color.base_white
                            )
                        ),
                        source.length,
                        source.length + toName.length,
                        Spanned.SPAN_INCLUSIVE_EXCLUSIVE
                    )
                    ssb.append(spanText).append("\n")
                }
                if (isToMe) {
                    val source = "私聊  "
                    spanText = SpannableString("${source}我")
                    spanText.setSpan(
                        ForegroundColorSpan(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_live_product_color)),
                        source.length,
                        "${source}我".length,
                        Spanned.SPAN_INCLUSIVE_EXCLUSIVE
                    )
                    ssb.append(spanText).append("\n")
                }
            }
            when (viewHolder) {
                is TextViewHolder -> {
                    bindData(viewHolder.dataBinding, message)
                    if (showGroupName(message.from.group)) {
                        viewHolder.dataBinding.chatGroupName.visibility = View.VISIBLE
                        viewHolder.dataBinding.chatGroupName.text =
                            String.format(getString(R.string.live_chat_group), routerViewModel.liveRoom.onlineUserVM.groupMap?.get(message.from.group)?.groupItemModel?.name?:"")
                    } else {
                        viewHolder.dataBinding.chatGroupName.visibility = View.GONE
                    }
                    with(viewHolder.chatMessageView) {
                        setChatMessageListener(this@ChatPadFragment)
                        textView.movementMethod = LinkMovementClickMethod.getInstance()
                        textView.setTextColor(ContextCompat.getColor(context!!, R.color.pad_message_text_color))
                        ssb.append(getMixText(message.content, textView))
                        if (!TextUtils.isEmpty(ssb)) {
                            ssb.setSpan(lineHeightSpan, 0, ssb.length - 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
                        }
                        textView.text = ssb
                        setMessageContainerBackground(if (message.from.number == routerViewModel.liveRoom.currentUser.number) getMySelfMsgBG() else getOtherMsgBG())
                        if (context != null) {
                            setDivideLineColor(
                                if (message.from.number == routerViewModel.liveRoom.currentUser.number) ContextCompat.getColor(
                                    context!!,
                                    R.color.base_divider_line_myself
                                ) else ContextCompat.getColor(context!!, R.color.base_divider_line_other)
                            )
                        }
                        if (message.from.number == routerViewModel.liveRoom.currentUser.number) {
                            setTextColor(ContextCompat.getColor(context!!, R.color.base_white))
                        } else {
                            setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_window_main_text_color))
                        }
                        textView.isFocusable = false
                        textView.isClickable = false
                        textView.isLongClickable = false
                        enableTranslation(
                            (routerViewModel.liveRoom.partnerConfig.isEnableChatTranslation
                                    && message.messageType != LPConstants.MessageType.Emoji
                                    && message.messageType != LPConstants.MessageType.EmojiWithName)
                        )
                        setMessageModel(message)
                        setTranslateButtonVisibility(getTranslateText(message.content).isNotEmpty() && !isOnlyEmojis(message.content))
                        removeReference()
                        if (message.reference != null) {
                            addRefrenceMessage()
                            val referenceMessage = message.reference.content
                            val referenceMessageSsb = SpannableStringBuilder()
                            referenceMessageSsb.append(getMixText(referenceMessage, tvReference))
                            if (!TextUtils.isEmpty(referenceMessage)) {
                                referenceMessageSsb.setSpan(lineHeightSpan, 0, referenceMessage.length - 1, Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
                            }
                            tvReference.text = referenceMessageSsb
                        }
                        removeTranslate()
                        addTranslateMessage(chatViewModel.getTranslateResult(position))
                        setOnProgressListener {
                            //判断是否有中文，有就翻译成英文，没有就翻译成中文
                            val fromLanguage = "auto"
                            val toLanguage = if (languageTranslateTo.isBlank()) "zh" else languageTranslateTo
                            val messageModel = message as LPMessageModel
                            if (messageModel.translateLanguage == toLanguage && isTranslate) {
                                removeTranslate()
                                chatViewModel.removeTranslateResult(message)
                            } else {
                                messageModel.translateLanguage = toLanguage
                                chatViewModel.translateMessage(getTranslateText(message.content), message.from.userId + message.time.time, fromLanguage, toLanguage)
                            }
                        }
                        if (message.from.type == LPConstants.LPUserType.Teacher || message.from.type == LPConstants.LPUserType.Assistant) {
                            Linkify.addLinks(textView, Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES)
                        } else {
                            textView.autoLinkMask = 0
                        }
                    }
                }
                is ImageViewHolder -> {
                    bindData(viewHolder.dataBinding, message)
                    if (showGroupName(message.from.group)) {
                        viewHolder.dataBinding.chatGroupName.visibility = View.VISIBLE
                        viewHolder.dataBinding.chatGroupName.text =
                            String.format(getString(R.string.live_chat_group), routerViewModel.liveRoom.onlineUserVM.groupMap?.get(message.from.group)?.groupItemModel?.name?:"")
                    } else {
                        viewHolder.dataBinding.chatGroupName.visibility = View.GONE
                    }
                    viewHolder.ivImg.setOnClickListener(null)
                    if (message is UploadingImageModel) {
                        val options = BitmapFactory.Options()
                        options.inJustDecodeBounds = true
                        BitmapFactory.decodeFile(message.getUrl(), options)
                        val size = intArrayOf(options.outWidth, options.outHeight)
                        ChatImageUtil.calculateImageSize(
                            size,
                            DisplayUtils.dip2px(context!!, 100f),
                            DisplayUtils.dip2px(context!!, 50f)
                        )

                        var requestOptions = RequestOptions()
                        requestOptions = requestOptions.override(size[0], size[1])
                            .placeholder(failedColorDrawable)
                            .error(failedColorDrawable)
                        context?.let {
                            Glide.with(it).load(File(message.getUrl()))
                                .apply(requestOptions)
                                .into(viewHolder.ivImg)
                        }

                        if (message.status == UploadingImageModel.STATUS_UPLOADING) {
                            viewHolder.tvMask.visibility = View.VISIBLE
                            viewHolder.tvExclamation.visibility = View.GONE
                        } else if (message.status == UploadingImageModel.STATUS_UPLOAD_FAILED) {
                            viewHolder.tvMask.visibility = View.GONE
                            viewHolder.tvExclamation.visibility = View.VISIBLE
                            viewHolder.ivImg.setOnClickListener {
                                chatViewModel.continueUploadQueue()
                            }
                        }
                    } else {
                        val target = ImageTarget(context, viewHolder.ivImg)
                        var requestOptions = RequestOptions()
                        requestOptions = requestOptions.override(300, 300)
                            .placeholder(failedColorDrawable)
                            .error(failedColorDrawable)
                        context?.let {
                            Glide.with(it).asBitmap()
                                .load(AliCloudImageUtil.getScaledUrl(message.url, AliCloudImageUtil.SCALED_MFIT, 300, 300))
                                .apply(requestOptions)
                                .into(target)
                        }
                        with(viewHolder) {
                            tvMask.visibility = View.GONE
                            tvExclamation.visibility = View.GONE
                        }
                        val gestureDetectorCompat = GestureDetectorCompat(context, PressListener(message, viewHolder, true))
                        viewHolder.ivImg.setOnTouchListener { _, event ->
                            gestureDetectorCompat.onTouchEvent(event)
                            true
                        }
                    }
                }
            }
        }

        private fun showGroupName(group: Int): Boolean {
            if (routerViewModel.liveRoom.partnerConfig.liveChatShowGroupName == 1 && group != 0) {
                // 大班老师或者助教显示分组
                return if (routerViewModel.liveRoom.isTeacherOrAssistant) {
                    true
                } else if (routerViewModel.liveRoom.isGroupTeacherOrAssistant) {
                    // 小班助教、老师只看本组则需判断是不是同组
                    if (routerViewModel.liveRoom.onlineUserVM.enableMyGroupUsersPublish()) {
                        routerViewModel.liveRoom.currentUser.group == group
                    } else {
                        true
                    }
                } else {
                    false
                }
            }
            return false
        }

        private fun getOtherMsgBG() = DrawableBuilder()
            .solidColor(ContextCompat.getColor(context!!, R.color.base_main_color_layer_20))
            .cornerRadius(DisplayUtils.dip2px(context!!, 8f))
            .build()

        private fun getMySelfMsgBG() = DrawableBuilder()
            .solidColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_live_product_color))
            .cornerRadius(DisplayUtils.dip2px(context!!, 8f))
            .build()

        private fun showOptMenu(viewHolder: RecyclerView.ViewHolder, userModel: IUserModel) {
            if (userModel !is LPUserModel) {
                return
            }
            viewHolder.itemView.chat_user_name.setOnClickListener {
                ChatOptMenuHelper.showOptMenu(context, routerViewModel, it, userModel, true)
            }
            viewHolder.itemView.chat_user_avatar.setOnClickListener {
                ChatOptMenuHelper.showOptMenu(context, routerViewModel, it, userModel, true)
            }
        }

        override fun getItemViewType(position: Int): Int {
            return when (chatViewModel.getMessage(position).messageType) {
                LPConstants.MessageType.Text, LPConstants.MessageType.Emoji, LPConstants.MessageType.EmojiWithName -> MESSAGE_TYPE_TEXT
                LPConstants.MessageType.Image -> MESSAGE_TYPE_IMAGE
                else -> MESSAGE_TYPE_TEXT
            }
        }

        private fun bindData(dataBinding: ItemPadChatBinding, message: IMessageModel) {
            dataBinding.message = message
            dataBinding.chatFragment = this@ChatPadFragment
        }
    }

    private fun currentUserId() = routerViewModel.liveRoom.currentUser.userId

    fun getNameFromMessage(message: IMessageModel): String {
        return CommonUtils.getEncodePhoneNumber(message.from.name)
    }

    fun getRoleFromMessage(message: IMessageModel): String {
        var role = ""
        if (message.from.type == LPConstants.LPUserType.Teacher) {
            role = if (TextUtils.isEmpty(routerViewModel.liveRoom.customizeTeacherLabel))
                getString(R.string.live_teacher) else routerViewModel.liveRoom.customizeTeacherLabel
        }
        if (message.from.type == LPConstants.LPUserType.Assistant) {
            role = if (TextUtils.isEmpty(routerViewModel.liveRoom.customizeAssistantLabel))
                getString(R.string.live_assistent) else routerViewModel.liveRoom.customizeAssistantLabel
        }
        return if (role.isNotEmpty()) {
            "[ $role ]"
        } else {
            ""
        }
    }

    fun getMessageTime(message: IMessageModel): String = simpleDataFormat.format(message.time)

    fun getClientTypeRes(message: IMessageModel): Drawable? {
        val clientIcon: Drawable?
        when (message.from.endType) {
            LPConstants.LPEndType.PC_Client -> {
                clientIcon =
                    context?.let { ContextCompat.getDrawable(it, R.drawable.ic_chat_client_pc) }
            }
            LPConstants.LPEndType.PC_H5 -> {
                clientIcon = context?.let {
                    ContextCompat.getDrawable(
                        it,
                        R.drawable.ic_chat_client_phone_h5
                    )
                }
            }
            LPConstants.LPEndType.PC_HTML -> {
                clientIcon =
                    context?.let { ContextCompat.getDrawable(it, R.drawable.ic_chat_client_pc_web) }
            }
            LPConstants.LPEndType.PC_MAC_Client -> {
                clientIcon =
                    context?.let { ContextCompat.getDrawable(it, R.drawable.ic_chat_client_mac) }
            }
            LPConstants.LPEndType.Android -> {
                clientIcon = context?.let {
                    ContextCompat.getDrawable(
                        it,
                        R.drawable.ic_chat_client_android
                    )
                }
            }
            LPConstants.LPEndType.iOS -> {
                clientIcon =
                    context?.let { ContextCompat.getDrawable(it, R.drawable.ic_chat_client_ios) }
            }
            else -> {
                clientIcon =
                    context?.let { ContextCompat.getDrawable(it, R.drawable.ic_chat_client_unkown) }
            }
        }
        return clientIcon
    }

    /**
     * 翻译去除表情中的[大笑]
     *
     * @param content
     * @return
     */
    private fun getTranslateText(srcContent: String): String {
        var content = srcContent
        val m = pattern.matcher(content)
        while (m.find()) {
            val group = m.group()
            if (chatViewModel.expressions.containsKey(group)) {
                content = content.replace(group, "")
            }
        }
        return content
    }

    private fun getMixText(srcContent: String, textView: TextView): SpannableStringBuilder {
        val matcher = pattern.matcher(srcContent)
        val ssb = SpannableStringBuilder(srcContent)
        while (matcher.find()) {
            val group = matcher.group()
            if (chatViewModel.expressions.containsKey(group)) {
                val drawable = URLImageParser(
                    textView,
                    textView.textSize
                ).getDrawable(chatViewModel.expressions[group])
                val centerImageSpan = CenterImageSpan(drawable, ImageSpan.ALIGN_BASELINE)
                ssb.setSpan(
                    centerImageSpan,
                    matcher.start(),
                    matcher.end(),
                    Spanned.SPAN_EXCLUSIVE_INCLUSIVE
                )
                ssb.removeSpan(group)
            }
        }
        return ssb
    }

    private fun showBigChatPic(url: String) {
        showBigChatPic(url, null)
    }

    private fun showBigChatPic(
        url: String,
        onCancelSticky: ChatPictureViewFragment.IOnBigPicCancel?
    ) {
        val fragment = ChatPictureViewFragment.newInstance(url)
        if (onCancelSticky != null && (routerViewModel.liveRoom.isTeacherOrAssistant || routerViewModel.liveRoom.isGroupTeacherOrAssistant)) {
            fragment.setOnBigPicCancel(onCancelSticky)
        }
        val presenter = ChatPictureViewPresenter()
        presenter.setRouter((activity as LiveRoomBaseActivity).routerListener)
        fragment.setPresenter(presenter)
        showDialogFragment(fragment)
    }

    private fun showSavePicDialog(bmpArray: ByteArray) {
        val fragment = ChatSavePicDialogFragment()
        val presenter = ChatSavePicDialogPresenter(bmpArray)
        presenter.setRouter((activity as LiveRoomBaseActivity).routerListener)
        fragment.setPresenter(presenter)
        showDialogFragment(fragment)
    }

    /**
     * 保存图片
     */
    private fun saveImageToGallery(bmpArray: ByteArray) {
        LPRxUtils.dispose(savePictureDisposable)
        savePictureDisposable = Observable.just(1)
            .observeOn(Schedulers.io())
            .map {
                // 首先保存图片
                val appDir = File(Environment.getExternalStorageDirectory(), "bjhl_lp_image")
                if (!appDir.exists()) {
                    appDir.mkdir()
                }
                val fileName = System.currentTimeMillis().toString() + ".jpg"
                val file = File(appDir, fileName)
                try {
                    val bmp = BitmapFactory.decodeByteArray(bmpArray, 0, bmpArray.size)
                    val fos = FileOutputStream(file)
                    bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos)
                    fos.flush()
                    fos.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }

                // 其次把文件插入到系统图库
                try {
                    MediaStore.Images.Media.insertImage(
                        context?.contentResolver,
                        file.absolutePath, fileName, null
                    )
                } catch (e: FileNotFoundException) {
                    e.printStackTrace()
                }
                file
            }
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { file -> showToastMessage("图片保存在" + file.absolutePath) }
    }

    private fun showNoPrivateChat() {
        fragment_chat_private_status_container.visibility = View.GONE
    }

    private fun showHavingPrivateChat(privateChatUser: IUserModel) {
        if (!routerViewModel.liveRoom.chatVM.isLiveCanWhisper) {
            return
        }
        if (context == null) {
            return
        }
        fragment_chat_private_status_container.visibility = View.VISIBLE
        val content = getString(R.string.private_chat) + privateChatUser.name
        val spannableString = SpannableString(content)
        if (content.length >= 3) {
            spannableString.setSpan(
                ForegroundColorSpan(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_live_product_color)),
                3,
                content.length,
                Spanned.SPAN_INCLUSIVE_INCLUSIVE
            )
        }
        fragment_chat_private_user.text = spannableString
    }

    private fun filterMessage(filter: Boolean) {
        chatViewModel.filterMessage = filter
        messageAdapter.notifyDataSetChanged()
        fragment_chat_filter.visibility = if (filter) View.VISIBLE else View.GONE
        if (!filter && messageAdapter.itemCount > 0) {
            // 取消只看老师后滑动到底部
            recyclerView.smoothScrollToPosition(messageAdapter.itemCount - 1)
        }
    }

    private fun getEncodedName(userModel: IUserModel): String {
        return CommonUtils.getEncodePhoneNumber(userModel.name)
    }

    override fun showMenu(x: Int, y: Int, parentView: View, iMessageModel: IMessageModel, isImage: Boolean) {
        context?.run {
            val popupWindow = PopupWindow(this)
            popupWindow.isFocusable = true
            popupWindow.width = DisplayUtils.dip2px(this, 80f)
            popupWindow.height = ViewGroup.LayoutParams.WRAP_CONTENT
            popupWindow.setBackgroundDrawable(ColorDrawable(0))

            val items = ArrayList<String>()
            val recallStatus = chatViewModel.getRecallStatus(iMessageModel)
            if (recallStatus == ChatMessageView.RECALL) {
                items.add(context!!.getString(R.string.live_chat_recall))
            }
            if (recallStatus == ChatMessageView.DELETE) {
                items.add(context!!.getString(R.string.live_chat_delete))
            }
            items.add(context!!.getString(R.string.live_chat_copy))
            if ((routerViewModel.liveRoom.isTeacherOrAssistant || routerViewModel.liveRoom.isGroupTeacherOrAssistant)) {
                if (containsMessageInSticky(iMessageModel)) {
                    items.add(context!!.getString(R.string.live_chat_sticky_cancel))
                } else {
                    items.add(context!!.getString(R.string.live_chat_sticky))
                }
            }
            if (routerViewModel.liveRoom.currentUser != iMessageModel.from && routerViewModel.liveRoom.partnerConfig.enableRoomChatReport && "HuaWeiStore" == CommonUtils.getChannel(context)) {
                items.add(getString(R.string.bjy_base_chat_report))
            }

            val listView = ListView(context)
            with(listView) {
                val bgDrawable = GradientDrawable()
                bgDrawable.setColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(context, R.attr.base_theme_window_bg_color))
                bgDrawable.setStroke(1, ContextCompat.getColor(context, R.color.base_bg_stroke))
                bgDrawable.cornerRadius = context!!.resources.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius).toFloat()
                background = bgDrawable
                this.adapter = ArrayAdapter(context, R.layout.bjy_menu_chat_message, items.toTypedArray())
                dividerHeight = 0
                setPadding(0, DisplayUtils.dip2px(context, 2f), 0, DisplayUtils.dip2px(context!!, 2f))
                setOnItemClickListener { _, _, position, _ ->
                    when (items[position]) {
                        resources.getString(R.string.live_chat_copy) -> {
                            if (isImage) {
                                copy("[img:" + iMessageModel.url + "]")
                            } else {
                                copy(iMessageModel.content)
                            }
                        }
                        getString(R.string.live_chat_sticky) -> {
                            addSticky(iMessageModel)
                        }
                        getString(R.string.live_chat_sticky_cancel) -> {
                            cancelSticky(iMessageModel)
                        }
                        getString(R.string.bjy_base_chat_report) -> {
                            val reportDialog = ReportDialog(context)
                            reportDialog.submitListener = object : ReportDialog.IReportSubmitListener {
                                override fun onSubmit(reasonList: MutableList<String>) {
                                    chatViewModel.reportMessage(context, reasonList, iMessageModel)
                                    reportDialog.dismiss()
                                }
                            }
                            reportDialog.show()
                        }
                        else -> {
                            chatViewModel.reCallMessage(iMessageModel)
                        }
                    }
                    popupWindow.dismiss()
                }
            }
            popupWindow.contentView = listView
            popupWindow.showAtLocation(parentView, Gravity.NO_GRAVITY, x - popupWindow.width / 2, y - popupWindow.height)
        }
    }

    private fun copy(copyStr: String): Boolean {
        return try {
            //获取剪贴板管理器
            val cm = context!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            // 创建普通字符型ClipData
            val mClipData = ClipData.newPlainText("Label", copyStr)
            // 将ClipData内容放到系统剪贴板里。
            cm.setPrimaryClip(mClipData)
            true
        } catch (e: Exception) {
            false
        }

    }


    inner class PressListener(private val iMessageModel: IMessageModel?, holder: RecyclerView.ViewHolder, private var isImage: Boolean) : GestureDetector.SimpleOnGestureListener() {
        private var parent: View? = null
        private var position = 0

        init {
            this.parent = holder.itemView
            this.position = holder.adapterPosition
        }

        override fun onLongPress(e: MotionEvent) {
            super.onLongPress(e)
            if (parent == null || iMessageModel == null) {
                return
            }
            showMenu(e.rawX.toInt(), e.rawY.toInt(), parent!!, iMessageModel, isImage)
        }

        override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
            if (!isImage || iMessageModel == null) {
                return true
            }
            showBigChatPic(iMessageModel.url)
            return true
        }
    }

    class TextViewHolder(val dataBinding: ItemPadChatBinding, itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        val chatMessageView: ChatMessageView = itemView.findViewById(R.id.chat_message_content)
    }

    class ImageViewHolder(val dataBinding: ItemPadChatBinding, itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        private val tvName: TextView = itemView.findViewById(R.id.item_chat_image_name)
        val tvExclamation: TextView = itemView.findViewById(R.id.item_chat_image_exclamation)
        val ivImg: ImageView = itemView.findViewById(R.id.item_chat_image)
        val tvMask: TextView = itemView.findViewById(R.id.item_chat_image_mask)

        init {
            tvName.visibility = View.GONE
        }
    }

    private class ImageTarget(context: Context?, private val imageView: ImageView) :
        SimpleTarget<Bitmap>() {
        private val mContext: WeakReference<Context?> = WeakReference(context)

        override fun onResourceReady(bitmap: Bitmap, transition: Transition<in Bitmap>?) {
            val context = mContext.get() ?: return
            val lp = imageView.layoutParams as RelativeLayout.LayoutParams
            val size = intArrayOf(bitmap.width, bitmap.height)
            ChatImageUtil.calculateImageSize(
                size,
                DisplayUtils.dip2px(context, 100f),
                DisplayUtils.dip2px(context, 50f)
            )
            lp.width = size[0]
            lp.height = size[1]
            imageView.layoutParams = lp
            imageView.setImageBitmap(bitmap)
        }
    }

    private class LanguageSelectMenuAdapter(
        mutableList: MutableList<String>,
        context: Context,
        position: Int
    ) : BaseAdapter() {
        private val mData: MutableList<String> = mutableList
        private val mContext: Context = context
        private val selectPosition = position
        override fun getCount(): Int {
            return mData.size
        }

        override fun getItem(position: Int): Any {
            return mData[position]
        }

        override fun getItemId(position: Int): Long {
            return position.toLong()
        }

        @SuppressLint("ViewHolder")
        override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
            val view =
                LayoutInflater.from(mContext).inflate(R.layout.bjy_language_select_menu, null)
            view.findViewById<TextView>(R.id.tv_language).text = mData[position]
            view.findViewById<TextView>(R.id.tv_language).setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(mContext, R.attr.base_theme_window_main_text_color))
            if (position == selectPosition) {
                view.findViewById<ImageView>(R.id.ic_language_is_selected).visibility = View.VISIBLE
                view.findViewById<TextView>(R.id.tv_language).setTextColor(ThemeDataUtil.getColorFromThemeConfigByAttrId(mContext, R.attr.base_theme_live_product_color))
            }
            return view
        }
    }

    companion object {
        fun newInstance() = ChatPadFragment()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        routerViewModel.actionNavigateToMain.removeObserver(navigateToMainObserver)
        LPRxUtils.dispose(savePictureDisposable)
        LPRxUtils.dispose(lotteryTimerDispose)
    }
}